/**
  **************************************************************************
  * @file     main.c
  * @brief    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f435_437_board.h"
#include "at32f435_437_clock.h"


#include "at32_emac.h"
#include "ethernetif.h"
#include "netconf.h"

#include "FreeRTOS.h"
#include "task.h"
/** @addtogroup AT32F437_periph_template
  * @{
  */

/** @addtogroup 437_LED_toggle LED_toggle
  * @{
  */

#define DELAY                            100
#define FAST                             1
#define SLOW                             4

uint8_t g_speed = FAST;

TaskHandle_t StartTask_Handler;
TaskHandle_t LedTask_Handler;
TaskHandle_t KeyTask_Handler;
TaskHandle_t EthTask_Handler;

void Start_task(void *pvParameters);
void Led_task(void *pvParameters);
void Key_task(void *pvParameters);
void Eth_task(void *pvParameters);

void button_exint_init(void);
void button_isr(void);

/**
  * @brief  configure button exint
  * @param  none
  * @retval none
  */
void button_exint_init(void)
{
  exint_init_type exint_init_struct;

  crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE0);

  exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = EXINT_LINE_0;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(EXINT0_IRQn, 0, 0);
}

/**
  * @brief  button handler function
  * @param  none
  * @retval none
  */
void button_isr(void)
{
  /* delay 5ms */
  delay_ms(5);

  /* clear interrupt pending bit */
  exint_flag_clear(EXINT_LINE_0);

  /* check input pin state */
  if(SET == gpio_input_data_bit_read(USER_BUTTON_PORT, USER_BUTTON_PIN))
  {
    if(g_speed == SLOW)
      g_speed = FAST;
    else
      g_speed = SLOW;
  }
}

/**
  * @brief  exint0 interrupt handler
  * @param  none
  * @retval none
  */
void EXINT0_IRQHandler(void)
{
  button_isr();
}

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  led_init();
  button_exint_init();
  printf("sys init ok.\r\n");

  traceSTART();

  xTaskCreate(
              (TaskFunction_t) Start_task,
              (const char*   ) "start_task",
              (uint16_t      ) 128,
              (void*         ) NULL,
              (UBaseType_t   ) 1,
              (TaskHandle_t* ) &StartTask_Handler
            );
  vTaskStartScheduler();
  while(1)
  {
    at32_led_toggle(LED2);
    delay_ms(g_speed * DELAY);
    at32_led_toggle(LED3);
    delay_ms(g_speed * DELAY);
    at32_led_toggle(LED4);
    delay_ms(g_speed * DELAY);
  }
}


/**
  * @}
  */
void Start_task(void *pvParameters)
{
  taskENTER_CRITICAL();



  xTaskCreate(
  	          	(TaskFunction_t) Led_task,
  	         	(const char*   ) "led_task",
  	          	(uint16_t      ) 128,
  	            (void*         ) NULL,
  	          	(UBaseType_t   ) 2,
  	         	(TaskHandle_t* ) &LedTask_Handler
              );
   xTaskCreate(
  	          	(TaskFunction_t) Key_task,
  	         	(const char*   ) "key_task",
  	          	(uint16_t      ) 128,
  	            (void*         ) NULL,
  	          	(UBaseType_t   ) 2,
  	         	(TaskHandle_t* ) &KeyTask_Handler
              );
   xTaskCreate(
  	          	(TaskFunction_t) Eth_task,
  	         	(const char*   ) "eth_task",
  	          	(uint16_t      ) 2048,
  	            (void*         ) NULL,
  	          	(UBaseType_t   ) 3,
  	         	(TaskHandle_t* ) &EthTask_Handler
              );
	vTaskDelete(StartTask_Handler);

	taskEXIT_CRITICAL();
}
/**
  * @
  */
void Led_task(void *pvParameters)
{
	while(1)
	{
		LEDRED = 1;
		vTaskDelay(300);
		LEDRED = 0;
		vTaskDelay(300);
		printf("this is taks led.\r\n");
	}
}
/**
  * @}
  */
void Key_task(void *pvParameters)
{
	while(1)
	{
		LEDYELLOW = 0;
		vTaskDelay(500);
		LEDYELLOW = 1;
		vTaskDelay(500);
		printf("this is taks key.\r\n");
	}
}
/**
  * @}
  */
void Eth_task(void *pvParameters)
{
	while(emac_system_init() == ERROR);
	tcpip_stack_init();

	while(1)
	{
		LEDGREEN = 0;
		vTaskDelay(800);
		LEDGREEN = 1;
		vTaskDelay(800);
		printf("this is taks eth.\r\n");
	}
}

/**
  * @}
  */
/*********************************************************************
*
*       vApplicationGetIdleTaskMemory()
*
*/
#if configSUPPORT_STATIC_ALLOCATION == 1
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) {
  /* If the buffers to be provided to the Idle task are declared inside this
  function then they must be declared static - otherwise they will be allocated on
  the stack and so not exists after this function exits. */
  static StaticTask_t xIdleTaskTCB;
  static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];

  /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
  state will be stored. */
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

  /* Pass out the array that will be used as the Idle task's stack. */
  *ppxIdleTaskStackBuffer = uxIdleTaskStack;

  /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
  Note that, as the array is necessarily of type StackType_t,
  configMINIMAL_STACK_SIZE is specified in words, not bytes. */
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
#endif

/*********************************************************************
*
*       vApplicationGetTimerTaskMemory()
*
*/
/*-----------------------------------------------------------*/

#if configSUPPORT_STATIC_ALLOCATION == 1
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) {
  /* If the buffers to be provided to the Timer task are declared inside this
  function then they must be declared static - otherwise they will be allocated on
  the stack and so not exists after this function exits. */
  static StaticTask_t xTimerTaskTCB;
  static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];

  /* Pass out a pointer to the StaticTask_t structure in which the Timer
  task's state will be stored. */
  *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

  /* Pass out the array that will be used as the Timer task's stack. */
  *ppxTimerTaskStackBuffer = uxTimerTaskStack;

  /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
  Note that, as the array is necessarily of type StackType_t,
  configMINIMAL_STACK_SIZE is specified in words, not bytes. */
  *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif
/*********************************************************************
*
*       vApplicationMallocFailedHook
*
*  Function description
*    Called if a call to pvPortMalloc() fails because there
*    is insufficient free memory available in the FreeRTOS heap.
*    pvPortMalloc() is called internally by FreeRTOS API functions
*    that create tasks, queues, software timers, and semaphores.
*    The size of the FreeRTOS heap is set by the configTOTAL_HEAP_SIZE
*    configuration constant in FreeRTOSConfig.h
*
*/
void vApplicationMallocFailedHook(void);
void vApplicationMallocFailedHook(void) {
  taskDISABLE_INTERRUPTS();
  for( ;; );
}

/*********************************************************************
*
*       vApplicationStackOverflowHook
*
*  Function description
*    Run time stack overflow checking is performed if
*    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.
*    This hook function is called if a stack overflow is detected.
*/
void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) {
  ( void ) pcTaskName;
  ( void ) xTask;
  taskDISABLE_INTERRUPTS();
  for( ;; );
}

/*********************************************************************
*
*       vApplicationIdleHook
*
*  Function description
*    This function is called on each cycle of the idle task.
*    In this case it does nothing useful, other than report
*    the amount of FreeRTOS heap that remains unallocated.
*
*/
void vApplicationIdleHook(void) {
#if configSUPPORT_DYNAMIC_ALLOCATION == 1
  volatile size_t xFreeHeapSpace;

  xFreeHeapSpace = xPortGetFreeHeapSize();
  if( xFreeHeapSpace > 100 ) {
    //
    // By now, the kernel has allocated everything it is going to, so
    // if there is a lot of heap remaining unallocated then
    // the value of configTOTAL_HEAP_SIZE in FreeRTOSConfig.h can be
    // reduced accordingly.
  }
#endif
}

/*********************************************************************
*
*       vMainConfigureTimerForRunTimeStats
*
*  Function description
*    The Blinky build configuration does not include run time
*    stats gathering, however, the Full and Blinky build configurations
*    share a FreeRTOSConfig.h file.
*    Therefore, dummy run time stats functions need to be defined
*    to keep the linker happy.
*
*/
void vMainConfigureTimerForRunTimeStats(void);
void vMainConfigureTimerForRunTimeStats(void) {
}

/*********************************************************************
*
*       ulMainGetRunTimeCounterValue
*
*/
unsigned long ulMainGetRunTimeCounterValue(void);
unsigned long ulMainGetRunTimeCounterValue(void) {
  return 0UL;
}

/*********************************************************************
*
*       vApplicationTickHook
*
*  Function description
*    A tick hook is used by the "Full" build configuration.
*    The Full and blinky build configurations share a FreeRTOSConfig.h
*    header file, so this simple build configuration also has to define
*    a tick hook - even though it does not actually use it for anything.
*
*/
void vApplicationTickHook(void);
void vApplicationTickHook(void) {
}


/**
  * @}
  */
